#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "NamedElement.h"
#include "RedefinableElement.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Activity;
class ActivityEdge;
class ActivityGroup;
class ActivityPartition;
class InterruptibleActivityRegion;
class RedefinableElement;
class StructuredActivityNode;

/// <summary>
/// ActivityNode
/// ActivityNode is an abstract class for points in the flow of an Activity
/// connected by ActivityEdges.
/// </summary>
class UMLMODEL_EXPORT ActivityNode : public NamedElement, public RedefinableElement {

public: // Constructors and destructors
    explicit ActivityNode(const QString& umlType="uml::ActivityNode");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// containingActivity
    /// The Activity that directly or indirectly contains this ActivityNode.
    /// </summary>
    virtual shared_ptr<Activity> containingActivity() const;

    /// <summary>
    /// isConsistentWith
    /// </summary>
    bool isConsistentWith(shared_ptr<RedefinableElement> redefiningElement) const override;

public: // Properties
    /// <summary>
    /// activity getter
    /// The Activity containing the ActivityNode, if it is directly owned by an
    /// Activity.
    /// </summary>
    shared_ptr<Activity> activity() const;

    /// <summary>
    /// activity setter
    /// The Activity containing the ActivityNode, if it is directly owned by an
    /// Activity.
    /// </summary>
    void setActivity(shared_ptr<Activity> value);

    /// <summary>
    /// inGroups getter
    /// ActivityGroups containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityGroup>>& inGroups();

    /// <summary>
    /// inInterruptibleRegions getter
    /// InterruptibleActivityRegions containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<InterruptibleActivityRegion>>& inInterruptibleRegions();

    /// <summary>
    /// inPartitions getter
    /// ActivityPartitions containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityPartition>>& inPartitions();

    /// <summary>
    /// inStructuredNode getter
    /// The StructuredActivityNode containing the ActvityNode, if it is directly owned
    /// by a StructuredActivityNode.
    /// </summary>
    shared_ptr<StructuredActivityNode> inStructuredNode() const;

    /// <summary>
    /// inStructuredNode setter
    /// The StructuredActivityNode containing the ActvityNode, if it is directly owned
    /// by a StructuredActivityNode.
    /// </summary>
    void setInStructuredNode(shared_ptr<StructuredActivityNode> value);

    /// <summary>
    /// incomings getter
    /// ActivityEdges that have the ActivityNode as their target.
    /// </summary>
    vector<shared_ptr<ActivityEdge>>& incomings();

    /// <summary>
    /// outgoings getter
    /// ActivityEdges that have the ActivityNode as their source.
    /// </summary>
    vector<shared_ptr<ActivityEdge>>& outgoings();

    /// <summary>
    /// redefinedNodes getter
    /// ActivityNodes from a generalization of the Activity containining this
    /// ActivityNode that are redefined by this ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityNode>>& redefinedNodes();

private: // Fields
    /// <summary>
    /// activity
    /// The Activity containing the ActivityNode, if it is directly owned by an
    /// Activity.
    /// </summary>
    shared_ptr<Activity> activity_;

    /// <summary>
    /// inGroups
    /// ActivityGroups containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityGroup>> inGroups_;

    /// <summary>
    /// inInterruptibleRegions
    /// InterruptibleActivityRegions containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<InterruptibleActivityRegion>> inInterruptibleRegions_;

    /// <summary>
    /// inPartitions
    /// ActivityPartitions containing the ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityPartition>> inPartitions_;

    /// <summary>
    /// inStructuredNode
    /// The StructuredActivityNode containing the ActvityNode, if it is directly owned
    /// by a StructuredActivityNode.
    /// </summary>
    shared_ptr<StructuredActivityNode> inStructuredNode_;

    /// <summary>
    /// incomings
    /// ActivityEdges that have the ActivityNode as their target.
    /// </summary>
    vector<shared_ptr<ActivityEdge>> incomings_;

    /// <summary>
    /// outgoings
    /// ActivityEdges that have the ActivityNode as their source.
    /// </summary>
    vector<shared_ptr<ActivityEdge>> outgoings_;

    /// <summary>
    /// redefinedNodes
    /// ActivityNodes from a generalization of the Activity containining this
    /// ActivityNode that are redefined by this ActivityNode.
    /// </summary>
    vector<shared_ptr<ActivityNode>> redefinedNodes_;

};

} // namespace uml
